import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, ExtraTreesClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.model_selection import train_test_split
import joblib
import itertools

# 1. 加载数据（训练集和测试集）
train_file_path = r'D:\develop\PythonCode\python基础\附_项目实战\十_反无人机大赛\data\train.csv'
test_file_path = r'D:\develop\PythonCode\python基础\附_项目实战\十_反无人机大赛\data\val.csv'

train_data = pd.read_csv(train_file_path)
test_data = pd.read_csv(test_file_path)

# 2. 检查缺失值，并清理数据
train_data = train_data.dropna()
test_data = test_data.dropna()

# 3. 分离特征和标签
X_train = train_data.drop('标签', axis=1)
y_train = train_data['标签']
X_test = test_data.drop('标签', axis=1)
y_test = test_data['标签']

# 4. 特征标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 5. 模型训练与评估函数
def train_and_evaluate_model(model, model_name, X_train_sub, X_test_sub, y_train, y_test):
    model.fit(X_train_sub, y_train)
    y_pred = model.predict(X_test_sub)

    # 计算各项指标
    acc = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred, average='macro')  # 'macro' 计算所有类的平均精度
    recall = recall_score(y_test, y_pred, average='macro')
    f1 = f1_score(y_test, y_pred, average='macro')

    # 打印结果
    print(f"{model_name} - acc: {acc:.16f}, precision: {precision:.16f}, recall: {recall:.16f}, f1: {f1:.16f}")
    return acc

# 6. 生成特征组合，并选择最佳特征组合
def find_best_feature_combination(model, model_name, X_train_scaled, X_test_scaled, y_train, y_test):
    best_acc = 0
    best_features = None

    feature_names = X_train.columns
    n_features = X_train_scaled.shape[1]

    # 遍历所有可能的特征组合
    for r in range(1, n_features + 1):  # 从1到n个特征的组合
        for feature_combination in itertools.combinations(range(n_features), r):
            # 选择特征子集
            X_train_sub = X_train_scaled[:, feature_combination]
            X_test_sub = X_test_scaled[:, feature_combination]

            # 训练和评估模型
            acc = train_and_evaluate_model(model, model_name, X_train_sub, X_test_sub, y_train, y_test)

            # 更新最佳特征组合
            if acc > best_acc:
                best_acc = acc
                best_features = feature_combination

    print(f"最佳特征组合: {best_features}，最佳准确率: {best_acc:.16f}")
    return best_features

# 7. 各模型的训练与评估
models = {
    # "随机森林": RandomForestClassifier(random_state=42),
    # "支持向量机": SVC(random_state=42),
    # "逻辑回归": LogisticRegression(random_state=42),
    # "K近邻": KNeighborsClassifier(),
    # "决策树": DecisionTreeClassifier(random_state=42),
    # "梯度提升树": GradientBoostingClassifier(random_state=42),
    "极限随机树": ExtraTreesClassifier(random_state=42),
    # "XGBoost": xgb.XGBClassifier(random_state=42),
    # "朴素贝叶斯": GaussianNB(),
}

# 8. 遍历每个模型并寻找最佳特征组合
for model_name, model in models.items():
    print(f"正在处理模型: {model_name}")
    best_features = find_best_feature_combination(model, model_name, X_train_scaled, X_test_scaled, y_train, y_test)

    # 使用最佳特征组合进行最终模型训练和保存
    X_train_best = X_train_scaled[:, best_features]
    X_test_best = X_test_scaled[:, best_features]
    model.fit(X_train_best, y_train)
    y_pred = model.predict(X_test_best)

    # 计算最终指标
    acc = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred, average='macro')
    recall = recall_score(y_test, y_pred, average='macro')
    f1 = f1_score(y_test, y_pred, average='macro')

    print(f"{model_name} 最终模型 - acc: {acc:.16f}, precision: {precision:.16f}, recall: {recall:.16f}, f1: {f1:.16f}")

    # 保存最终模型
    joblib.dump(model, f"{model_name}_best_model.pkl")
